<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>使用 Vue + TypeScript 开发 Chrome Extensions 🐱‍👤 | 人间熙攘，好久不见</title>
    <meta name="generator" content="VuePress 1.7.1">
    <link rel="icon" href="/favicon.ico">
    <script charset="utf-8" crossorigin="anonymous" src="/js/rainyday.js"></script>
    <meta name="description" content="人间熙攘，好久不见~ Magic 的博客">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    <meta name="google-site-verification" content="cFm07VssWCh93-dPrep06FyYb3ST7MIfQnx9B6ZcYsQ">
    
    <link rel="preload" href="/assets/css/0.styles.fe1de732.css" as="style"><link rel="preload" href="/assets/js/app.fe0f04fe.js" as="script"><link rel="preload" href="/assets/js/3.8f0a3ee6.js" as="script"><link rel="preload" href="/assets/js/1.0d4da6ad.js" as="script"><link rel="preload" href="/assets/js/13.ef37c62d.js" as="script"><link rel="prefetch" href="/assets/js/10.c5719ae1.js"><link rel="prefetch" href="/assets/js/11.22795e1d.js"><link rel="prefetch" href="/assets/js/12.35a1eee1.js"><link rel="prefetch" href="/assets/js/14.f36a185b.js"><link rel="prefetch" href="/assets/js/15.06ade84c.js"><link rel="prefetch" href="/assets/js/16.3d06e6fb.js"><link rel="prefetch" href="/assets/js/17.7dd5742a.js"><link rel="prefetch" href="/assets/js/18.7bff1c11.js"><link rel="prefetch" href="/assets/js/19.7bb3239d.js"><link rel="prefetch" href="/assets/js/20.501cb431.js"><link rel="prefetch" href="/assets/js/21.8cfea759.js"><link rel="prefetch" href="/assets/js/22.ef6af803.js"><link rel="prefetch" href="/assets/js/23.8b263173.js"><link rel="prefetch" href="/assets/js/24.dd9f70b8.js"><link rel="prefetch" href="/assets/js/25.4ec78de4.js"><link rel="prefetch" href="/assets/js/26.8e7888cc.js"><link rel="prefetch" href="/assets/js/27.a78de168.js"><link rel="prefetch" href="/assets/js/28.9faf1a01.js"><link rel="prefetch" href="/assets/js/4.a1817f8d.js"><link rel="prefetch" href="/assets/js/5.779f467f.js"><link rel="prefetch" href="/assets/js/6.6a2cdf6b.js"><link rel="prefetch" href="/assets/js/7.ccf4b6c6.js"><link rel="prefetch" href="/assets/js/8.27e71aa7.js"><link rel="prefetch" href="/assets/js/9.6dcd52b0.js">
    <link rel="stylesheet" href="/assets/css/0.styles.fe1de732.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container" data-v-2d5f533b><div data-v-2d5f533b><div id="loader-wrapper" class="loading-wrapper" data-v-d48f4d20 data-v-2d5f533b data-v-2d5f533b><div class="loader-main" data-v-d48f4d20><div data-v-d48f4d20></div><div data-v-d48f4d20></div><div data-v-d48f4d20></div><div data-v-d48f4d20></div></div> <!----> <!----></div> <div class="password-shadow password-wrapper-out" style="display:none;" data-v-64685f0e data-v-2d5f533b data-v-2d5f533b><h3 class="title" style="display:none;" data-v-64685f0e data-v-64685f0e>人间熙攘，好久不见</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-64685f0e data-v-64685f0e><input type="password" value="" data-v-64685f0e> <span data-v-64685f0e>Konck! Knock!</span> <button data-v-64685f0e>OK</button></label> <div class="footer" style="display:none;" data-v-64685f0e data-v-64685f0e><span data-v-64685f0e><i class="iconfont reco-theme" data-v-64685f0e></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-64685f0e>vuePress-theme-reco</a></span> <span data-v-64685f0e><i class="iconfont reco-copyright" data-v-64685f0e></i> <a data-v-64685f0e><span data-v-64685f0e>Magic</span>
            
          <span data-v-64685f0e>2017 - </span>
          2022
        </a></span></div></div> <div class="hide" data-v-2d5f533b><header class="navbar" data-v-2d5f533b><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/logo/nav.png" alt="人间熙攘，好久不见" class="logo"> <span class="site-name">人间熙攘，好久不见</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link"><i class="iconfont reco-home"></i>
  Home
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-category"></i>
      Category
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/tools/" class="nav-link"><i class="iconfont undefined"></i>
  tools
</a></li><li class="dropdown-item"><!----> <a href="/categories/Zsh/" class="nav-link"><i class="iconfont undefined"></i>
  Zsh
</a></li><li class="dropdown-item"><!----> <a href="/categories/iTerm2/" class="nav-link"><i class="iconfont undefined"></i>
  iTerm2
</a></li><li class="dropdown-item"><!----> <a href="/categories/Front-end/" class="nav-link"><i class="iconfont undefined"></i>
  Front-end
</a></li><li class="dropdown-item"><!----> <a href="/categories/版本控制-Git/" class="nav-link"><i class="iconfont undefined"></i>
  版本控制-Git
</a></li><li class="dropdown-item"><!----> <a href="/categories/Rust/" class="nav-link"><i class="iconfont undefined"></i>
  Rust
</a></li><li class="dropdown-item"><!----> <a href="/categories/skia-safe/" class="nav-link"><i class="iconfont undefined"></i>
  skia-safe
</a></li><li class="dropdown-item"><!----> <a href="/categories/第三方对接/" class="nav-link"><i class="iconfont undefined"></i>
  第三方对接
</a></li><li class="dropdown-item"><!----> <a href="/categories/Powershell/" class="nav-link"><i class="iconfont undefined"></i>
  Powershell
</a></li><li class="dropdown-item"><!----> <a href="/categories/python/" class="nav-link"><i class="iconfont undefined"></i>
  python
</a></li><li class="dropdown-item"><!----> <a href="/categories/wsl2/" class="nav-link"><i class="iconfont undefined"></i>
  wsl2
</a></li></ul></div></div><div class="nav-item"><a href="/tag/" class="nav-link"><i class="iconfont reco-tag"></i>
  Tags
</a></div><div class="nav-item"><a href="/timeline/" class="nav-link"><i class="iconfont reco-date"></i>
  TimeLine
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont undefined"></i>
      GitHub
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://github.com/magicLaLa/Magic.me" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://github.com/magicLaLa/blog" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  Before
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask" data-v-2d5f533b></div> <aside class="sidebar" data-v-2d5f533b><div class="personal-info-wrapper" data-v-ca798c94 data-v-2d5f533b><img src="/logo/avatar2.gif" alt="author-avatar" class="personal-img" data-v-ca798c94> <h3 class="name" data-v-ca798c94>
    Magic
  </h3> <div class="num" data-v-ca798c94><div data-v-ca798c94><h3 data-v-ca798c94>18</h3> <h6 data-v-ca798c94>文章</h6></div> <div data-v-ca798c94><h3 data-v-ca798c94>11</h3> <h6 data-v-ca798c94>标签</h6></div></div> <hr data-v-ca798c94></div> <nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link"><i class="iconfont reco-home"></i>
  Home
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-category"></i>
      Category
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/tools/" class="nav-link"><i class="iconfont undefined"></i>
  tools
</a></li><li class="dropdown-item"><!----> <a href="/categories/Zsh/" class="nav-link"><i class="iconfont undefined"></i>
  Zsh
</a></li><li class="dropdown-item"><!----> <a href="/categories/iTerm2/" class="nav-link"><i class="iconfont undefined"></i>
  iTerm2
</a></li><li class="dropdown-item"><!----> <a href="/categories/Front-end/" class="nav-link"><i class="iconfont undefined"></i>
  Front-end
</a></li><li class="dropdown-item"><!----> <a href="/categories/版本控制-Git/" class="nav-link"><i class="iconfont undefined"></i>
  版本控制-Git
</a></li><li class="dropdown-item"><!----> <a href="/categories/Rust/" class="nav-link"><i class="iconfont undefined"></i>
  Rust
</a></li><li class="dropdown-item"><!----> <a href="/categories/skia-safe/" class="nav-link"><i class="iconfont undefined"></i>
  skia-safe
</a></li><li class="dropdown-item"><!----> <a href="/categories/第三方对接/" class="nav-link"><i class="iconfont undefined"></i>
  第三方对接
</a></li><li class="dropdown-item"><!----> <a href="/categories/Powershell/" class="nav-link"><i class="iconfont undefined"></i>
  Powershell
</a></li><li class="dropdown-item"><!----> <a href="/categories/python/" class="nav-link"><i class="iconfont undefined"></i>
  python
</a></li><li class="dropdown-item"><!----> <a href="/categories/wsl2/" class="nav-link"><i class="iconfont undefined"></i>
  wsl2
</a></li></ul></div></div><div class="nav-item"><a href="/tag/" class="nav-link"><i class="iconfont reco-tag"></i>
  Tags
</a></div><div class="nav-item"><a href="/timeline/" class="nav-link"><i class="iconfont reco-date"></i>
  TimeLine
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont undefined"></i>
      GitHub
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://github.com/magicLaLa/Magic.me" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://github.com/magicLaLa/blog" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont undefined"></i>
  Before
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav> <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>FrontEnd</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/Contents/FrontEnd/ChromeExtensions.html" aria-current="page" class="active sidebar-link">使用 Vue + TypeScript 开发 Chrome Extensions 🐱‍👤</a></li><li><a href="/Contents/FrontEnd/DebounceAndthrottling.html" class="sidebar-link">Debounce Throttling ~</a></li><li><a href="/Contents/FrontEnd/Performance.html" class="sidebar-link">Performance Yes 🎉</a></li><li><a href="/Contents/FrontEnd/RollupAndTsToNpmPackage.html" class="sidebar-link">Rollup + Typescript =&gt; NPM Package</a></li></ul></section></li></ul> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-64685f0e data-v-2d5f533b><h3 class="title" style="display:none;" data-v-64685f0e data-v-64685f0e>使用 Vue + TypeScript 开发 Chrome Extensions 🐱‍👤</h3> <!----> <label id="box" class="inputBox" style="display:none;" data-v-64685f0e data-v-64685f0e><input type="password" value="" data-v-64685f0e> <span data-v-64685f0e>Konck! Knock!</span> <button data-v-64685f0e>OK</button></label> <div class="footer" style="display:none;" data-v-64685f0e data-v-64685f0e><span data-v-64685f0e><i class="iconfont reco-theme" data-v-64685f0e></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-64685f0e>vuePress-theme-reco</a></span> <span data-v-64685f0e><i class="iconfont reco-copyright" data-v-64685f0e></i> <a data-v-64685f0e><span data-v-64685f0e>Magic</span>
            
          <span data-v-64685f0e>2017 - </span>
          2022
        </a></span></div></div> <div data-v-2d5f533b><main class="page"><div class="page-title" style="display:none;"><h1 class="title">使用 Vue + TypeScript 开发 Chrome Extensions 🐱‍👤</h1> <div data-v-3b7f5bdf><i class="iconfont reco-account" data-v-3b7f5bdf><span data-v-3b7f5bdf>Magic</span></i> <i class="iconfont reco-date" data-v-3b7f5bdf><span data-v-3b7f5bdf>2020-12-08</span></i> <i class="iconfont reco-eye" data-v-3b7f5bdf><span id="/Contents/FrontEnd/ChromeExtensions.html" data-flag-title="Your Article Title" class="leancloud-visitors" data-v-3b7f5bdf><a class="leancloud-visitors-count" style="font-size:.9rem;font-weight:normal;color:#999;"></a></span></i> <i class="iconfont reco-tag tags" data-v-3b7f5bdf><span class="tag-item" data-v-3b7f5bdf>Front-end</span><span class="tag-item" data-v-3b7f5bdf>Chrome</span></i></div></div> <div class="theme-reco-content content__default" style="display:none;"><h1 id="chrome-extensions"><a href="#chrome-extensions" class="header-anchor">#</a> Chrome Extensions</h1> <h2 id="谷歌插件是什么"><a href="#谷歌插件是什么" class="header-anchor">#</a> 谷歌插件是什么？</h2> <p>严格来说，我们目前所说的插件其实是 <em>Chrome 扩展程序(<code>Chrome Extensions</code>)</em>，根据官方文档上所说：<em>扩展程序是可以定制浏览体验的小型软件程序。它们使用户可以根据个人需要或偏好来定制Chrome功能和行为。它们基于Web技术（例如HTML，JavaScript和CSS）构建</em>，它是以 .crx 做结尾的压缩文件。</p> <h3 id="对我们有什么用呢"><a href="#对我们有什么用呢" class="header-anchor">#</a> 对我们有什么用呢？</h3> <p>我们可以很轻松的实现自己的定制版的浏览器，实现自己想要在浏览器上的自定义功能，因为它对网页有完全的方法问权限（<em>前提是自己使用，发布到商店的话会进行审查，移除不必要的权限，保证安全</em>）。</p> <h3 id="核心功能点"><a href="#核心功能点" class="header-anchor">#</a> 核心功能点</h3> <h4 id="manifest-json"><a href="#manifest-json" class="header-anchor">#</a> manifest.json</h4> <p><em>最新的版本为 <a href="https://developer.chrome.com/docs/extensions/mv3/intro/" target="_blank" rel="noopener noreferrer">v3 版本<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 从Chrome 88版支持并且 Chrome Web Store 自 2021年1月 开始支持，并且Chrome Web Store从2021年1月开始支持。目前插件大部分都是使用的 <a href="https://developer.chrome.com/docs/extensions/mv2/" target="_blank" rel="noopener noreferrer">v2 版本<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></em></p> <p>manifest 格式可以到 <a href="https://developer.chrome.com/docs/extensions/mv3/manifest/" target="_blank" rel="noopener noreferrer">manifest 查看<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，例如下结构，其中高亮为必填项。</p> <div class="language-json extra-class"><div class="highlight-lines"><br><div class="highlighted"> </div><div class="highlighted"> </div><br><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div><pre class="language-json"><code><span class="token punctuation">{</span>
	<span class="token property">&quot;manifest_version&quot;</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token comment">// 清单文件版本号</span>
	<span class="token property">&quot;name&quot;</span><span class="token operator">:</span> <span class="token string">&quot;scheme-chrome-extension&quot;</span><span class="token punctuation">,</span>
	<span class="token property">&quot;description&quot;</span><span class="token operator">:</span> <span class="token string">&quot;scheme 生成、分析、转换，暂时仅支持支付宝小程序&quot;</span><span class="token punctuation">,</span>
	<span class="token property">&quot;version&quot;</span><span class="token operator">:</span> <span class="token string">&quot;0.0.2&quot;</span><span class="token punctuation">,</span>
	<span class="token property">&quot;browser_action&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// 浏览器右上角图标设置，browser_action、page_action、app 必须三选一</span>
		<span class="token property">&quot;default_title&quot;</span><span class="token operator">:</span> <span class="token string">&quot;vue-chrome-extension&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;default_icon&quot;</span><span class="token operator">:</span> <span class="token string">&quot;assets/scheme-128.png&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;default_popup&quot;</span><span class="token operator">:</span> <span class="token string">&quot;popup.html&quot;</span>
	<span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// 省略...</span>
	<span class="token property">&quot;permissions&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
	<span class="token property">&quot;icons&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
		<span class="token property">&quot;16&quot;</span><span class="token operator">:</span> <span class="token string">&quot;assets/scheme-16.png&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;48&quot;</span><span class="token operator">:</span> <span class="token string">&quot;assets/scheme-48.png&quot;</span><span class="token punctuation">,</span>
		<span class="token property">&quot;128&quot;</span><span class="token operator">:</span> <span class="token string">&quot;assets/scheme-128.png&quot;</span>
	<span class="token punctuation">}</span><span class="token punctuation">,</span>
	<span class="token property">&quot;content_security_policy&quot;</span><span class="token operator">:</span> <span class="token string">&quot;script-src 'self' 'unsafe-eval'; object-src 'self'&quot;</span><span class="token punctuation">,</span>
	<span class="token property">&quot;web_accessible_resources&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;fonts/*&quot;</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
</code></pre></div><h5 id="popup"><a href="#popup" class="header-anchor">#</a> Popup</h5> <p>Popup 是点击<code>browser_action</code> 或者 <code>page_action</code> 图标时打开的一个小窗口网页，焦点离开网页就立即关闭，一般用来做一些临时性的交互，(<strong>v3 情况下改为同一个为<code>action</code></strong>)如下图：</p> <p><img src="/assets/img/ex-tmp.0306649a.png" alt="scheme-chrome-extension"></p> <p>Popup 弹窗可以自适应大小，由于弹窗是点击打开的，所以生命周期很短暂，弹窗消失掉就回销毁，所以需要长时间运行的代码不要放到这个页面中，可以放到 <code>background</code> 中。</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token comment">// v2</span>
<span class="token property">&quot;browser_action&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// 浏览器右上角图标设置，browser_action、page_action、app 必须三选一</span>
  <span class="token property">&quot;default_title&quot;</span><span class="token operator">:</span> <span class="token string">&quot;scheme-chrome-extension&quot;</span><span class="token punctuation">,</span>
  <span class="token property">&quot;default_icon&quot;</span><span class="token operator">:</span> <span class="token string">&quot;assets/scheme-128.png&quot;</span><span class="token punctuation">,</span>
  <span class="token property">&quot;default_popup&quot;</span><span class="token operator">:</span> <span class="token string">&quot;popup.html&quot;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// v3</span>
<span class="token property">&quot;action&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>...<span class="token punctuation">}</span>
</code></pre></div><h5 id="background"><a href="#background" class="header-anchor">#</a> Background</h5> <p>它是一个常驻的后台页面，生命周期在插件中所有类型的页面是最长的，所以需要长时间运行的代码或者启动就运行的代码可以放到这个里面执行。可以通过 <code>page</code> 指定 网页 或者 <code>script</code> 指定一个 js</p> <div class="language-json extra-class"><div class="highlight-lines"><br><br><br><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><br><br><br></div><pre class="language-json"><code><span class="token punctuation">{</span>
  <span class="token property">&quot;name&quot;</span><span class="token operator">:</span> <span class="token string">&quot;My extension&quot;</span><span class="token punctuation">,</span>
  ...
  <span class="token property">&quot;background&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">&quot;scripts&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;background.js&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token comment">// &quot;page&quot;: &quot;background.html&quot;,</span>
    <span class="token property">&quot;persistent&quot;</span><span class="token operator">:</span> <span class="token boolean">false</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  ...
<span class="token punctuation">}</span>
</code></pre></div><p>可以看到 有一个 <a href="https://developer.chrome.com/docs/extensions/mv3/background_migration/" target="_blank" rel="noopener noreferrer"><code>persistent</code> 事件驱动<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 参数：</p> <ul><li>true: 随着浏览器打开/关闭才会开始/关闭</li> <li>false: 在被需要时加载，在空闲时被关闭，通过 事件触发，不会常驻</li></ul> <p><em>v3版本有一个提议是 <a href="https://developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/" target="_blank" rel="noopener noreferrer">Migrating from background pages to service workers<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></em></p> <h5 id="content-scripts"><a href="#content-scripts" class="header-anchor">#</a> Content_scripts</h5> <p>其实就是插件向被访问的页面注入脚本，支持 js 和 css。</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span>
	<span class="token property">&quot;content_scripts&quot;</span><span class="token operator">:</span>
	<span class="token punctuation">[</span>
		<span class="token punctuation">{</span>
			<span class="token comment">//&quot;matches&quot;: [&quot;http://*/*&quot;, &quot;https://*/*&quot;],</span>
			<span class="token comment">// &quot;&lt;all_urls&gt;&quot; 表示匹配所有地址</span>
			<span class="token property">&quot;matches&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;&lt;all_urls&gt;&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
			<span class="token comment">// 多个JS按顺序注入</span>
			<span class="token property">&quot;js&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;js/jquery-1.8.3.js&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;js/content-script.js&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
			<span class="token comment">// JS的注入可以随便一点，但是CSS的注意就要千万小心了，因为一不小心就可能影响全局样式</span>
			<span class="token property">&quot;css&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;css/custom.css&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
			<span class="token comment">// 代码注入的时间，可选值： &quot;document_start&quot;, &quot;document_end&quot;, or &quot;document_idle&quot;，最后一个表示页面空闲时，默认document_idle</span>
			<span class="token property">&quot;run_at&quot;</span><span class="token operator">:</span> <span class="token string">&quot;document_start&quot;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p><code>content-scripts</code> 和 原始页面共享DOM，但是不共享JS，如要访问页面JS（例如某个JS变量），只能通过注入js文件来实现。<code>content-scripts</code>不能访问绝大部分<code>chrome.xxx.api</code>，除了下面这4种：</p> <ul><li>chrome.extension(getURL , inIncognitoContext , lastError , onRequest , sendRequest)</li> <li>chrome.i18n</li> <li>chrome.runtime(connect , getManifest , getURL , id , onConnect , onMessage , sendMessage)</li> <li>chrome.storage
其实看到这里不要悲观，这些API绝大部分时候都够用了，非要调用其它API的话，可以通过事件通信来实现让background来帮你调用。</li></ul> <p>注入 js：就是通过在<code>content-scripts</code> 往 dom 中插入 <code>script</code> 文件来实现：</p> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">injectCustomJs</span><span class="token punctuation">(</span><span class="token parameter">jsPath</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
	jsPath <span class="token operator">=</span> jsPath <span class="token operator">||</span> <span class="token string">'js/inject.js'</span><span class="token punctuation">;</span>
	<span class="token keyword">const</span> temp <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'script'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	temp<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'type'</span><span class="token punctuation">,</span> <span class="token string">'text/javascript'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">// 获得的地址类似：chrome-extension://ihcokhadfjfchaeagdoclpnjdiokfakg/js/inject.js</span>
	temp<span class="token punctuation">.</span>src <span class="token operator">=</span> chrome<span class="token punctuation">.</span>extension<span class="token punctuation">.</span><span class="token function">getURL</span><span class="token punctuation">(</span>jsPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
	temp<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	<span class="token punctuation">{</span>
		<span class="token comment">// 放在页面不好看，执行完后移除掉</span>
		<span class="token keyword">this</span><span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>
	document<span class="token punctuation">.</span>head<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>temp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>高亮部分同时需要在 manifest.json 中配置声明文件，否则找不到文件：</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span>
  ...
  <span class="token property">&quot;web_accessible_resources&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;js/inject.js&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="搭建开发环境"><a href="#搭建开发环境" class="header-anchor">#</a> 搭建开发环境</h2> <p>推荐使用 <a href="https://cli.vuejs.org/zh/guide/" target="_blank" rel="noopener noreferrer">Vue-cli<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 搭建开发环境，按照多页面开发，因为插件本身就是多页面的，不支持页面之间的跳转（通过hash或者history）。</p> <h3 id="目录结构"><a href="#目录结构" class="header-anchor">#</a> 目录结构</h3> <div class="language-tree extra-class"><pre class="language-text"><code>.
├── dist
├── node_modules
├── public
├── src
│   ├─ assets
│   ├─ popup
│   ├─ types
│   ├─ utils
│   └── manifest.json
├── .eslintignore
├── .eslintrce
├── .gitignore
├── babel.config.js
├── tsconfig.json
├── vue.config.js
├── yarn.lock
└── package.json
</code></pre></div><h3 id="安装-zip-webpack-plugin"><a href="#安装-zip-webpack-plugin" class="header-anchor">#</a> 安装 zip-webpack-plugin</h3> <p>如果需要上传到 谷歌开发商店需要 zip 压缩文件，不需要上传则跳过这一步，后面的步骤也可以跳过 zip 相关逻辑。</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token function">yarn</span> <span class="token function">add</span> zip-webpack-plugin -D
</code></pre></div><h3 id="配置-vue-config-js-文件"><a href="#配置-vue-config-js-文件" class="header-anchor">#</a> 配置 vue.config.js 文件</h3> <ul><li><p>配置需要复制的文件</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 只需要复制的文件</span>
<span class="token keyword">const</span> copyFiles <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token keyword">from</span><span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'src/manifest.json'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    to<span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'dist'</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/manifest.json</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span>
    <span class="token keyword">from</span><span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'src/assets'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    to<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'dist/assets'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
</code></pre></div><ul><li>配置 <a href="https://github.com/xpl/crx-hotreload" target="_blank" rel="noopener noreferrer">hot-reload.js<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul> <p>注：这个文件是用来更新插件的，因为在使用 vue 热更新之后，如果不使用这个插件，你必须在插件页面手动刷新重新加载才可以获取到最新的包，关键代码如下：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">reload</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  window<span class="token punctuation">.</span>chrome<span class="token punctuation">.</span>tabs<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      active<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      currentWindow<span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token parameter">tabs</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token comment">// NB: see https://github.com/xpl/crx-hotreload/issues/5</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>tabs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          window<span class="token punctuation">.</span>chrome<span class="token punctuation">.</span>tabs<span class="token punctuation">.</span><span class="token function">reload</span><span class="token punctuation">(</span>tabs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>id<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      window<span class="token punctuation">.</span>chrome<span class="token punctuation">.</span>runtime<span class="token punctuation">.</span><span class="token function">reload</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><p>在开发环境下加载 <code>hot-reload.js</code> 文件：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">if</span> <span class="token punctuation">(</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">!==</span> <span class="token string">'production'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 正式不需要这个文件</span>
  copyFiles<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    <span class="token keyword">from</span><span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'src/utils/hot-reload.js'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    to<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'dist'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>增加拷贝的方法：</p> <div class="language-js extra-class"><pre class="language-js"><code>module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token operator">...</span>
  <span class="token function-variable function">chainWebpack</span><span class="token operator">:</span> <span class="token parameter">config</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// ^copy-webpack-plugin@5.6.0</span>
    config<span class="token punctuation">.</span><span class="token function">plugin</span><span class="token punctuation">(</span><span class="token string">'cpoy'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'copy-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>copyFiles<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// ^copy-webpack-plugin@6.0.0</span>
    <span class="token comment">// config.plugin('copy').use(require('copy-webpack-plugin'), [</span>
    <span class="token comment">//   {</span>
    <span class="token comment">//     patterns: [copyFiles],</span>
    <span class="token comment">//   },</span>
    <span class="token comment">// ]);</span>
    <span class="token operator">...</span>
  <span class="token punctuation">}</span>
  <span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre></div></li> <li><p>正式环境增加压缩配置</p></li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">if</span> <span class="token punctuation">(</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">===</span> <span class="token string">'production'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  plugins<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>
    <span class="token keyword">new</span> <span class="token class-name">ZipWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      path<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'dist'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
      filename<span class="token operator">:</span> <span class="token string">'dist.zip'</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li>处理字体文件</li></ul> <div class="language-js extra-class"><pre class="language-js"><code>module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token operator">...</span>
  <span class="token function-variable function">chainWebpack</span><span class="token operator">:</span> <span class="token parameter">config</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span>
    <span class="token comment">// 处理字体文件名，去除hash值</span>
    <span class="token keyword">const</span> fontsRule <span class="token operator">=</span> config<span class="token punctuation">.</span>module<span class="token punctuation">.</span><span class="token function">rule</span><span class="token punctuation">(</span><span class="token string">&quot;fonts&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">// 清除已有的所有 loader。</span>
      <span class="token comment">// 如果你不这样做，接下来的 loader 会附加在该规则现有的 loader 之后。</span>
      fontsRule<span class="token punctuation">.</span>uses<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      fontsRule<span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(woff2?|eot|ttf|otf)(\?.*)?$</span><span class="token regex-delimiter">/</span><span class="token regex-flags">i</span></span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'url'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">loader</span><span class="token punctuation">(</span><span class="token string">'url-loader'</span><span class="token punctuation">)</span>
        <span class="token punctuation">.</span><span class="token function">options</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          limit<span class="token operator">:</span> <span class="token number">1000</span><span class="token punctuation">,</span>
          name<span class="token operator">:</span> <span class="token string">'fonts/[name].[ext]'</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token operator">...</span>
  <span class="token punctuation">}</span>
  <span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li>插件页面</li></ul> <div class="language-js extra-class"><div class="highlight-lines"><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><br><div class="highlighted"> </div><br><br><br></div><pre class="language-js"><code><span class="token keyword">const</span> chromeNames <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token string">'popup'</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> pages <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
chromeNames<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">name</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  pages<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
    entry<span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">./src/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/main.ts</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
    template<span class="token operator">:</span> <span class="token string">'index.html'</span><span class="token punctuation">,</span>
    filename<span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.html</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>
    title<span class="token operator">:</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  pages<span class="token punctuation">,</span>
  <span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre></div><p><strong>注：完整的配置可以到 <a href="https://github.com/magicLaLa/scheme-chrome-extension/blob/main/vue.config.js" target="_blank" rel="noopener noreferrer">vue.config.js<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 参考</strong></p> <h3 id="配置-scripts-命令"><a href="#配置-scripts-命令" class="header-anchor">#</a> 配置 scripts 命令</h3> <div class="language-json extra-class"><div class="highlight-lines"><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br></div><pre class="language-json"><code><span class="token punctuation">{</span>
  ...
  <span class="token property">&quot;scripts&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token property">&quot;serve&quot;</span><span class="token operator">:</span> <span class="token string">&quot;npm run build-watch&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;build&quot;</span><span class="token operator">:</span> <span class="token string">&quot;vue-cli-service build&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;lint&quot;</span><span class="token operator">:</span> <span class="token string">&quot;vue-cli-service lint&quot;</span><span class="token punctuation">,</span>
    <span class="token property">&quot;build-watch&quot;</span><span class="token operator">:</span> <span class="token string">&quot;vue-cli-service build --watch&quot;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  ...
<span class="token punctuation">}</span>
</code></pre></div><h3 id="示例"><a href="#示例" class="header-anchor">#</a> 示例</h3> <h4 id="弹窗页面"><a href="#弹窗页面" class="header-anchor">#</a> 弹窗页面</h4> <ul><li>popup.vue</li></ul> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>el-container</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>el-header</span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>25px<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>header<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>小程序 scheme <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>i</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>el-icon-set-up<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>i</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>el-header</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>el-main</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>CollapseTemp</span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>el-main</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>el-container</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>ts<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">import</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> Vue <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'vue-property-decorator'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> CollapseTemp <span class="token keyword">from</span> <span class="token string">'@/popup/components/CollapseTemp.vue'</span><span class="token punctuation">;</span>

@<span class="token function">Component</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'Popup'</span><span class="token punctuation">,</span>
  components<span class="token operator">:</span> <span class="token punctuation">{</span>
    CollapseTemp<span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">class</span> <span class="token class-name">Popup</span> <span class="token keyword">extends</span> <span class="token class-name">Vue</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>scss<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token style"><span class="token language-css">
<span class="token selector">html,
body</span> <span class="token punctuation">{</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
  <span class="token property">padding</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>scss<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token style"><span class="token language-css">
...
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ul><li>main.ts</li></ul> <div class="language-ts extra-class"><pre class="language-ts"><code><span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">'vue'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> App <span class="token keyword">from</span> <span class="token string">'./App.vue'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token string">'element-ui/lib/theme-chalk/index.css'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>
  Container<span class="token punctuation">,</span>
  Header<span class="token punctuation">,</span>
  Main<span class="token punctuation">,</span>
  Collapse<span class="token punctuation">,</span>
  CollapseItem<span class="token punctuation">,</span>
  Form<span class="token punctuation">,</span>
  FormItem<span class="token punctuation">,</span>
  Input<span class="token punctuation">,</span>
  Button<span class="token punctuation">,</span>
  Message<span class="token punctuation">,</span>
  Alert<span class="token punctuation">,</span>
  Card<span class="token punctuation">,</span>
  Tooltip<span class="token punctuation">,</span>
<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'element-ui'</span><span class="token punctuation">;</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Container<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Header<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Main<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Collapse<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>CollapseItem<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Form<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>FormItem<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Input<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Button<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Alert<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Card<span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>Tooltip<span class="token punctuation">)</span><span class="token punctuation">;</span>

Vue<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>$message <span class="token operator">=</span> Message<span class="token punctuation">;</span>

Vue<span class="token punctuation">.</span>config<span class="token punctuation">.</span>productionTip <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>

<span class="token keyword">new</span> <span class="token class-name">Vue</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token function-variable function">render</span><span class="token operator">:</span> <span class="token punctuation">(</span>h<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token function">h</span><span class="token punctuation">(</span>App<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">$mount</span><span class="token punctuation">(</span><span class="token string">'#app'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p><strong>注： 完整代码可看 <a href="https://github.com/magicLaLa/scheme-chrome-extension" target="_blank" rel="noopener noreferrer">scheme-chrome-extension<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></strong></p> <p>之后开发插件的新页面可以先到 <code>vue.config.js</code> 中配置，然后在 <code>src/xxx</code> 下增加对应页面模板就可以愉快的进行开发了🤪</p> <p>🤩后续可以使用 <a href="https://github.com/vitejs/vite" target="_blank" rel="noopener noreferrer">vite<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 进行开发，因为更快~，并且也支持使用 react 进行开发，后续我们一起期待吧 😘</p></div> <footer class="page-edit" style="display:none;"><!----> <!----></footer> <!----> <!----> <!----></main> <!----></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-c6073ba8 data-v-c6073ba8><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-c6073ba8><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-c6073ba8></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-c6073ba8></path></svg></div><div class="kanbanniang" data-v-5775ee02><div class="banniang-container" style="display:;" data-v-5775ee02><div class="messageBox" style="right:68px;bottom:190px;display:none;" data-v-5775ee02>
      欢迎来到 人间熙攘，好久不见
    </div> <div class="operation" style="right:90px;bottom:40px;display:none;" data-v-5775ee02><i class="kbnfont kbn-ban-home ban-home" data-v-5775ee02></i> <i class="kbnfont kbn-ban-message message" data-v-5775ee02></i> <i class="kbnfont kbn-ban-close close" data-v-5775ee02></i> <a target="_blank" href="https://vuepress-theme-reco.recoluan.com/views/plugins/kanbanniang.html" data-v-5775ee02><i class="kbnfont kbn-ban-info info" data-v-5775ee02></i></a> <i class="kbnfont kbn-ban-theme skin" style="display:none;" data-v-5775ee02></i></div> <canvas id="banniang" width="150" height="220" class="live2d" style="right:90px;bottom:-20px;opacity:0.9;" data-v-5775ee02></canvas></div> <div class="showBanNiang" style="display:none;" data-v-5775ee02>
    看板娘
  </div></div><canvas id="vuepress-canvas-cursor"></canvas><canvas id="vuepress-canvas-ribbon"></canvas></div></div>
    <script src="/assets/js/app.fe0f04fe.js" defer></script><script src="/assets/js/3.8f0a3ee6.js" defer></script><script src="/assets/js/1.0d4da6ad.js" defer></script><script src="/assets/js/13.ef37c62d.js" defer></script>
  </body>
</html>
